package com.hyacinth.support;

import com.hyacinth.config.DBType;
import com.hyacinth.datasource.DataSourceManager;
import com.hyacinth.datasource.HYDateSource;
import com.hyacinth.domain.PageInfo;
import com.hyacinth.meta.DatabaseAnalyzer;
import com.hyacinth.meta.TableMetaData;
import com.hyacinth.utils.Assert;
import com.hyacinth.utils.DBInfoUtil;
import org.apache.commons.dbutils.QueryRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

/**
 * 数据操作处理器
 * @author zhangfb
 * @version 1.0.0.1
 * @since JDK 1.8
 */
public class DBOptionProcessor implements DBOption, Serializable {

    private static final Logger LOGGER = LoggerFactory.getLogger(DBOptionProcessor.class);

    private static final long serialVersionUID = 1L;

    private HYDateSource hyds;

    private DBType dbType;

    public DBOptionProcessor(DBType dbType, String ip, int port, String username, String password, String dbName) {
        this.dbType = dbType;
        String driver = DBInfoUtil.getDriver(dbType);
        String url = DBInfoUtil.getUrl(dbType, ip, port, dbName);
        hyds = DataSourceManager.getInstance().getDataSource(driver, url, username, password);
    }

    public DBOptionProcessor(DBType dbType, String ip, int port, String username, String password, String dbName, int poolSize) {
        this.dbType = dbType;
        String driver = DBInfoUtil.getDriver(dbType);
        String url = DBInfoUtil.getUrl(dbType, ip, port, dbName);
        hyds = DataSourceManager.getInstance().getDataSource(driver, url, username, password, poolSize);
    }

    public DBOptionProcessor(String driver, String url, String username, String password, int poolSize) {
        this.dbType = DBType.getByDriverName(driver);
        hyds = DataSourceManager.getInstance().getDataSource(driver, url, username, password, poolSize);
    }

    public DBOptionProcessor(String driver, String url, String username, String password) {
        this.dbType = DBType.getByDriverName(driver);
        hyds = DataSourceManager.getInstance().getDataSource(driver, url, username, password);
    }

    @Override
    public HYDateSource getHyds() {
        return hyds;
    }

    @Override
    public QueryRunner getQueryRunner() {
        return new QueryRunner(hyds.getDataSource());
    }

    /**
     * 获取数据库连接
     * @return 数据库连接
     * @throws SQLException sql 异常
     */
    @Override
    public Connection getConnect() throws SQLException {
        return hyds.getDataSource().getConnection();
    }

    @Override
    public List<TableMetaData> getTableMetaData(Connection conn, String dbName) throws SQLException {
        Assert.notNull(conn, "db connection is required");
        return DatabaseAnalyzer.getTablesSimple(conn, dbName);
    }

    /**
     * 执行ddl语句
     * @param conn     数据库连接
     * @param ddlSqls  SQL语句
     * @return 执行结果
     * @throws SQLException sql 异常
     */
    @Override
    public boolean execDDLSql(Connection conn, String... ddlSqls) throws SQLException {
        Statement statement = null;
        try {
            statement = conn.createStatement();
            for (String ddlSql : ddlSqls) {
                statement.executeUpdate(ddlSql);
            }
        } finally {
            if (statement != null) {
                statement.close();
            }
        }
        return true;
    }

    /**
     * 分页查询数据
     * @param dbName      数据库名称
     * @param tableName   表名称
     * @param currPage    当前页
     * @param pageSize    每页条数
     * @param sql         执行语句
     * @return 分页结果
     * @throws Exception 异常
     */
    @Override
    public PageInfo queryByPaging(String dbName, String tableName, long currPage, int pageSize, String sql) throws Exception {

//        new Pagination(getDBType(), getQueryRunner(), );
        return null;
    }

    @Override
    public void close(Connection conn) throws SQLException {
        Assert.notNull(conn, "db connection is required");
        conn.close();
    }

    @Override
    public DBType getDBType() {
        return this.dbType;
    }
}
